# -*- python -*-
# ex: set syntax=python:

# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# This is the buildmaster config file for the 'chromium' bot. It must
# be installed as 'master.cfg' in your buildmaster's base directory
# (although the filename can be changed with the --basedir option to
# 'mktap buildbot master').

# It has one job: define a dictionary named BuildmasterConfig. This
# dictionary has a variety of keys to control different aspects of the
# buildmaster. They are documented in docs/config.xhtml .

# This file follows this naming convention:
# Factories: f_cr_rel_[type]
# Builders:  b_chromium_rel_[os]_[type]
# BuildDir:  chromium-rel-[os]-[type]
#
# os = xp/vista/linux/mac
# type = perf

from buildbot.scheduler import Scheduler
from buildbot.scheduler import Triggerable

from common import chromium_utils

from master import chromium_notifier
from master import gitiles_poller
from master import master_config
from master import master_utils
from master import slaves_list
from master.factory import annotator_factory

import config
import master_site_config

ActiveMaster = master_site_config.ChromiumPerf


# Enable MAIL_NOTIFIER in production to send perf sheriff alerts.
MAIL_NOTIFIER = ActiveMaster.is_production_host

# This is the dictionary that the buildmaster pays attention to. We also use
# a shorter alias to save typing.
c = BuildmasterConfig = {}

# 'slavePortnum' defines the TCP port to listen on. This must match the value
# configured into the buildslaves (with their --master option)
c['slavePortnum'] = ActiveMaster.slave_port

# Disable compression for the stdio files.
c['logCompressionLimit'] = False

# Load the list of slaves.
slaves = slaves_list.SlavesList('slaves.cfg', 'ChromiumPerf')

config.DatabaseSetup(c, require_dbconfig=ActiveMaster.is_production_host)

def recipe_factory(recipe):
  f_annotations = annotator_factory.AnnotatorFactory(ActiveMaster)
  return f_annotations.BaseFactory(recipe=recipe)

# ------------------------------------------------------------------------------
# Benchmarks.
#
# FORMAT:
#   (EXPECTED_RUNTIME_MINUTES, TEST_NAME)
#
# To see runtimes, refer to:
# http://build.chromium.org/p/chromium.perf/stats
#
# Note that the benchmark list here is deprecated and are no longer used for
# android.
#
# Expected runtimes should be as accurate as possible to balance test sharding
# across slaves. The estimates here are calculated on Linux and then we assume
# other platforms are proportional.
#
# TODO: It would be really nice if buildbot could calculate these runtimes.


# End Benchmarks.
# ------------------------------------------------------------------------------


# ------------------------------------------------------------------------------
# Change Sources.

# Polls config.Master.trunk_url for changes
master_poller = gitiles_poller.GitilesPoller(
    'https://chromium.googlesource.com/chromium/src')

c['change_source'] = [master_poller]

# End Change Sources.
# ------------------------------------------------------------------------------


# ------------------------------------------------------------------------------
# Schedulers.

## configure the Schedulers

s_chromium = Scheduler(name='chromium',
                       branch='master',
                       treeStableTimer=60,
                       builderNames=['Android Builder',
                                     'Android arm64 Builder',
                                     'Win Builder',
                                     'Win x64 Builder',
                                     'Mac Builder',
                                     'Linux Builder',
                                    ])

s_chromium_android_rel_trigger = Triggerable('android_rel',
                                             ['Android Nexus4 Perf',
                                              'Android Nexus5 Perf',
                                              'Android Nexus6 Perf',
                                              'Android Nexus7v2 Perf',
                                              'Android One Perf',
                                             ])

s_chromium_android_rel_arm64_trigger = Triggerable('android_rel_arm64',
                                                   ['Android Nexus9 Perf'])

s_chromium_winrel_trigger = Triggerable('winrel',
                                        ['Win 8 Perf (1)',
                                         'Win 8 Perf (2)',
                                         'Win 7 Perf (1)',
                                         'Win 7 Perf (2)',
                                         'Win 7 Perf (3)',
                                         'Win 7 Perf (4)',
                                         'Win 7 Perf (5)',
                                         'Win 7 Intel GPU Perf',
                                         'Win 7 Low-End Perf (1)',
                                         'Win 7 Low-End Perf (2)',
                                         'Win XP Perf (1)',
                                         'Win XP Perf (2)',
                                         'Win XP Perf (3)',
                                         'Win XP Perf (4)',
                                         'Win XP Perf (5)',
                                        ])

s_chromium_winrel_x64_trigger = Triggerable('winrel_x64',
                                            ['Win 7 x64 Perf (1)',
                                             'Win 7 x64 Perf (2)',
                                             'Win 7 ATI GPU Perf (1)',
                                             'Win 7 ATI GPU Perf (2)',
                                             'Win 7 ATI GPU Perf (3)',
                                             'Win 7 ATI GPU Perf (4)',
                                             'Win 7 ATI GPU Perf (5)',
                                             'Win 7 Nvidia GPU Perf (1)',
                                             'Win 7 Nvidia GPU Perf (2)',
                                             'Win 7 Nvidia GPU Perf (3)',
                                             'Win 7 Nvidia GPU Perf (4)',
                                             'Win 7 Nvidia GPU Perf (5)'
                                            ])

# Scheduler to trigger slaves that depend on the mac release build.
s_chromium_macrel_trigger = Triggerable('macrel',
                                        ['Mac 10.9 Perf (1)',
                                         'Mac 10.9 Perf (2)',
                                         'Mac 10.9 Perf (3)',
                                         'Mac 10.9 Perf (4)',
                                         'Mac 10.9 Perf (5)',
                                         'Mac 10.8 Perf (1)',
                                         'Mac 10.8 Perf (2)',
                                         'Mac 10.8 Perf (3)',
                                         'Mac 10.8 Perf (4)',
                                         'Mac 10.8 Perf (5)',
                                        ])

s_chromium_linux_rel_trigger = Triggerable('linuxrel',
                                           ['Linux Perf (1)',
                                            'Linux Perf (2)',
                                            'Linux Perf (3)',
                                            'Linux Perf (4)',
                                            'Linux Perf (5)',
                                           ])

c['schedulers'] = [s_chromium,
                   s_chromium_android_rel_trigger,
                   s_chromium_android_rel_arm64_trigger,
                   s_chromium_winrel_trigger,
                   s_chromium_winrel_x64_trigger,
                   s_chromium_macrel_trigger,
                   s_chromium_linux_rel_trigger,
                  ]

# End Schedulers.
# ------------------------------------------------------------------------------


c['builders'] = []
# ----------------------------------------------------------------------------
# BUILDER DEFINITIONS

# The 'builders' list defines the Builders. Each one is configured with a
# dictionary, using the following keys:
#  name (required): the name used to describe this bilder
#  builddir (required): which subdirectory to run the builder in
#  factory (required): a BuildFactory to define how the build is run
#  periodicBuildTime (optional): if set, force a build every N seconds
#  category (optional): it is not used in the normal 'buildbot' meaning. It is
#                       used by gatekeeper to determine which steps it should
#                       look for to close the tree.
#

# 1. Builders

b_chromium_rel_android_builder = {'name': 'Android Builder',
  'factory': annotator_factory.AnnotatorFactory().BaseFactory(
      recipe='android/builder',
      triggers=['android_rel']),
  'category': '1builders|android',
}

b_chromium_rel_android_arm64_builder = {'name': 'Android arm64 Builder',
  'factory': annotator_factory.AnnotatorFactory().BaseFactory(
      recipe='android/builder',
      triggers=['android_rel_arm64']),
  'category': '1builders|android',
}

b_chromium_rel_win_builder = {'name': 'Win Builder',
  'builddir': 'chromium-rel-builder',
  'factory': annotator_factory.AnnotatorFactory().BaseFactory(
      recipe='chromium',
      triggers=['winrel'],
      timeout=4800),
  'category': '1builders|windows',
  'auto_reboot': False,
}

b_chromium_rel_win_x64_builder = {'name': 'Win x64 Builder',
  'builddir': 'chromium-rel-x64-builder',
  'factory': annotator_factory.AnnotatorFactory().BaseFactory(
      recipe='chromium',
      triggers=['winrel_x64'],
      timeout=4800),
  'category': '1builders|windows',
  'auto_reboot': False,
}

b_chromium_rel_mac_builder = {'name': 'Mac Builder',
  'builddir': 'chromium-rel-mac-builder',
  'factory': annotator_factory.AnnotatorFactory().BaseFactory(
      recipe='chromium',
      triggers=['macrel'],
      timeout=2400),
  'category': '1builders|mac',
  'auto_reboot': False,
}

b_chromium_rel_linux_builder = {'name': 'Linux Builder',
  'builddir': 'chromium-rel-linux',
  'factory': annotator_factory.AnnotatorFactory().BaseFactory(
      recipe='chromium',
      triggers=['linuxrel'],
      timeout=2400),
  'category': '1builders|linux',
  'auto_reboot': False,
}

# 2. Android

b_chromium_rel_android_nexus4 = {'name': 'Android Nexus4 Perf',
  'factory': recipe_factory('android/perf'),
  'category': '2android|builder_testers',
}

b_chromium_rel_android_nexus5 = {'name': 'Android Nexus5 Perf',
  'factory': recipe_factory('android/perf'),
  'category': '2android|builder_testers',
}

b_chromium_rel_android_nexus6 = {'name': 'Android Nexus6 Perf',
  'factory': recipe_factory('android/perf'),
  'category': '2android|builder_testers',
}

b_chromium_rel_android_nexus7v2 = {'name': 'Android Nexus7v2 Perf',
  'factory': recipe_factory('android/perf'),
  'category': '2android|builder_testers',
}

b_chromium_rel_android_nexus9 = {'name': 'Android Nexus9 Perf',
  'factory': recipe_factory('android/perf'),
  'category': '2android|builder_testers',
}

b_chromium_rel_android_one = {'name': 'Android One Perf',
  'factory': recipe_factory('android/perf'),
  'category': '2android|builder_testers',
}

c['builders'] = [
  b_chromium_rel_android_builder,
  b_chromium_rel_android_arm64_builder,
  b_chromium_rel_win_builder,
  b_chromium_rel_win_x64_builder,
  b_chromium_rel_mac_builder,
  b_chromium_rel_linux_builder,
  b_chromium_rel_android_nexus4,
  b_chromium_rel_android_nexus5,
  b_chromium_rel_android_nexus6,
  b_chromium_rel_android_nexus7v2,
  b_chromium_rel_android_nexus9,
  b_chromium_rel_android_one,
]

# 3. Windows
for i in range(0, 2):
  c['builders'].append({
    'name': 'Win 8 Perf (%d)' % (i + 1),
    'factory': recipe_factory('chromium'),
    'category': '3windows|builder_testers',
    })

for i in range(0, 5):
  c['builders'].append({
    'name': 'Win 7 Perf (%d)' % (i + 1),
    'factory': recipe_factory('chromium'),
    'category': '3windows|builder_testers',
    })

for i in range(0, 2):
  c['builders'].append({
    'name': 'Win 7 x64 Perf (%d)' % (i + 1),
    'factory': recipe_factory('chromium'),
    'category': '3windows|builder_testers',
    })

for i in range(0, 5):
  c['builders'].append({
    'name': 'Win 7 ATI GPU Perf (%d)' % (i + 1),
    'factory': recipe_factory('chromium'),
    'category': '3windows|builder_testers',
    })

c['builders'].append({'name': 'Win 7 Intel GPU Perf',
    'factory': recipe_factory('chromium'),
    'category': '3windows|builder_testers',
    })

for i in range(0, 5):
  c['builders'].append({
    'name': 'Win 7 Nvidia GPU Perf (%d)' % (i + 1),
    'factory': recipe_factory('chromium'),
    'category': '3windows|builder_testers',
    })

for i in range(0, 2):
  c['builders'].append({
    'name': 'Win 7 Low-End Perf (%d)' % (i + 1),
    'factory': recipe_factory('chromium'),
    'category': '3windows|builder_testers',
    })

for i in range(0, 5):
  c['builders'].append({
    'name': 'Win XP Perf (%d)' % (i + 1),
    'factory': recipe_factory('chromium'),
    'category': '3windows|builder_testers',
    })

# 4. Mac
for i in range(0, 5):
  c['builders'].append({
    'name': 'Mac 10.9 Perf (%d)' % (i + 1),
    'factory': recipe_factory('chromium'),
    'category': '4mac|builder_testers',
    })

for i in range(0, 5):
  c['builders'].append({
    'name': 'Mac 10.8 Perf (%d)' % (i + 1),
    'factory': recipe_factory('chromium'),
    'category': '4mac|builder_testers',
    })

# 5. Linux
for i in range(0, 5):
  c['builders'].append({
    'name': 'Linux Perf (%d)' % (i + 1),
    'factory': recipe_factory('chromium'),
    'category': '5linux|builder_testers',
    })

####### BUILDSLAVES

# Associate the slaves to the manual builders. The configuration is in
# slaves.cfg.
for builder in c['builders']:
  builder['slavenames'] = slaves.GetSlavesName(builder=builder['name'])

# The 'slaves' list defines the set of allowable buildslaves. List all the
# slaves registered to a builder. Remove dupes.
c['slaves'] = master_utils.AutoSetupSlaves(c['builders'],
                                           config.Master.GetBotPassword())
master_utils.VerifySetup(c, slaves)


####### STATUS TARGETS

# the 'buildbotURL' string should point to the location where the buildbot's
# internal web server (usually the html.Waterfall page) is visible. This
# typically uses the port number set in the Waterfall 'status' entry, but
# with an externally-visible host name which the buildbot cannot figure out
# without some help.

#Must come before AutoSetupMaster().
c['buildbotURL'] = ActiveMaster.buildbot_url

# Adds common status and tools to this master.
master_utils.AutoSetupMaster(c, ActiveMaster,
    public_html='../master.chromium/public_html',
    templates=['./templates', '../master.chromium/templates'],
    tagComparator=master_poller.comparator,
    enable_http_status_push=ActiveMaster.is_production_host)

# Add more.

if MAIL_NOTIFIER:
  c['status'].append(chromium_notifier.ChromiumNotifier(
      fromaddr=ActiveMaster.from_address,
      exclusions={},
      relayhost=config.Master.smtp,
      status_header='Perf alert on "%(builder)s":\n%(steps)s',
      subject='%(projectName)s %(builder)s %(result)s',
      extraRecipients=[],
      lookup=master_utils.FilterDomain(),
      sheriffs=['sheriff_perf'],
      public_html='../master.chromium/public_html',
      forgiving_steps=[],
      use_getname=True))

####### PROJECT IDENTITY

# the 'projectName' string will be used to describe the project that this
# buildbot is working on. For example, it is used as the title of the
# waterfall HTML page. The 'projectURL' string will be used to provide a link
# from buildbot HTML pages to your project's home page.

c['projectName'] = ActiveMaster.project_name
c['projectURL'] = config.Master.project_url
